Skip to content

fix(agentx): rerun DeepSeek-V4 B300 SGLang with OOM headroom / 修复 AgentX:为 DeepSeek-V4 B300 SGLang 重跑预留 OOM 余量#2226

Open
cquil11 wants to merge 2 commits into
mainfrom
agent/b300-dsv4-sglang-agentic-rerun
Open

fix(agentx): rerun DeepSeek-V4 B300 SGLang with OOM headroom / 修复 AgentX:为 DeepSeek-V4 B300 SGLang 重跑预留 OOM 余量#2226
cquil11 wants to merge 2 commits into
mainfrom
agent/b300-dsv4-sglang-agentic-rerun

Conversation

@cquil11

@cquil11 cquil11 commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Validation

  • bash -n benchmarks/single_node/agentic/dsv4_fp4_b300_sglang.sh
  • Parsed configs/nvidia-master.yaml with PyYAML.
  • Loaded and validated all 147 master configurations through utils.matrix_logic.validation.load_config_files.

中文说明

  • 作为 [Agentx][sglang] B200+B300 DeepSeek V4 AgentX config update #2145 的后续 PR,仅迁移 DeepSeek-V4-Pro FP4 B300 SGLang AgentX 启动脚本与搜索空间变更,并基于最新 main 重新构建分支。
  • 保留原 PR 中 B300 的 MegaMoE DEP 与低延迟 TP 配方,不包含 B200 变更及无关的 changelog 处理逻辑。
  • 将 DEP4 的 mem-fraction-static0.93 降至 0.90运行 29367944489 中 6 个看似卡住的 B300 任务实际在 deep_gemm.fp8_paged_mqa_logits 触发了调度器 CUDA OOM:当时仅剩 2.9–4.8 GiB 显存,却需要分配 4.2–6.1 GiB。降低该比例后,每张 GPU 可多预留约 8.6 GiB,同时仍高于实测模型分析器下限。
  • 本 PR 仅重跑 B300 配置;旧运行已在 [Agentx][sglang] B200+B300 DeepSeek V4 AgentX config update #2145 中固定引用,以复用其中已完成的结果。

验证

  • bash -n benchmarks/single_node/agentic/dsv4_fp4_b300_sglang.sh
  • 使用 PyYAML 解析 configs/nvidia-master.yaml
  • 通过 utils.matrix_logic.validation.load_config_files 加载并验证全部 147 个 master 配置。

Carry the B300-only SGLang AgentX recipe and search-space changes from PR #2145 onto current main. Reduce DEP4 mem-fraction-static from 0.93 to 0.90 after run 29367944489 showed sparse-attention indexer CUDA OOMs during warmup.\n\n中文:将原 PR #2145 中仅适用于 B300 的 SGLang AgentX 配方与搜索空间变更迁移到最新 main。根据运行 29367944489 在预热阶段出现的稀疏注意力索引器 CUDA OOM,将 DEP4 的 mem-fraction-static 从 0.93 降至 0.90,为激活值和工作区预留更多 HBM。
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase As a PR reviewer and CODEOWNER, I have reviewed this and have.

For PR verification, add the full-sweep-fail-fast label (strongly recommended) to this PR — the benchmark sweep only runs on labeled PRs. Use full-sweep-enabled only if you need matrix jobs to keep running past a failure.

PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs


感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 As a PR reviewer and CODEOWNER, I have reviewed this and have

如需进行 PR 验证,请为此 PR 添加 full-sweep-fail-fast 标签(强烈推荐)— 基准测试 sweep 仅在带有标签的 PR 上运行。仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled

PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase As a PR reviewer and CODEOWNER, I have reviewed this and have.

For PR verification, add the full-sweep-fail-fast label (strongly recommended) to this PR — the benchmark sweep only runs on labeled PRs. Use full-sweep-enabled only if you need matrix jobs to keep running past a failure.

PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs


感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 As a PR reviewer and CODEOWNER, I have reviewed this and have

如需进行 PR 验证,请为此 PR 添加 full-sweep-fail-fast 标签(强烈推荐)— 基准测试 sweep 仅在带有标签的 PR 上运行。仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled

PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase As a PR reviewer and CODEOWNER, I have reviewed this and have.

For PR verification, add the full-sweep-fail-fast label (strongly recommended) to this PR — the benchmark sweep only runs on labeled PRs. Use full-sweep-enabled only if you need matrix jobs to keep running past a failure.

PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs


感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 As a PR reviewer and CODEOWNER, I have reviewed this and have

如需进行 PR 验证,请为此 PR 添加 full-sweep-fail-fast 标签(强烈推荐)— 基准测试 sweep 仅在带有标签的 PR 上运行。仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled

PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档

Append the B300-only DeepSeek-V4 SGLang AgentX changelog entry for PR #2226.\n\n中文:为 PR #2226 追加仅针对 B300 的 DeepSeek-V4 SGLang AgentX 性能变更记录,以触发重跑。
@cquil11 cquil11 added agentx AgentX benchmarks, recipes, and infrastructure full-sweep-enabled labels Jul 15, 2026 — with ChatGPT Codex Connector
Comment on lines +143 to +163
MEM_FRACTION_STATIC=0.85
SWA_FULL_TOKENS_RATIO=0.075
# MegaMoE requires the default (non-compressed) attention path and fused shared experts.
MODEL_ARGS=()
EXTRA_ARGS=(--enable-prefill-delayer)
# chunked-prefill is divided by dp_size (=TP) under DP-attention; keep the
# effective chunk at 8192. Size the decode graph to served concurrency:
# DEP8 (dp 8) serves conc up to 512, DEP4 (dp 4) tops out near 128.
if [ "$TP" = "8" ]; then
CHUNKED_PREFILL_SIZE=65536
CUDA_GRAPH_ARGS=(--cuda-graph-max-bs-decode 544)
else
# DEP4 (TP4/EP4) shards the model across only 4 GPUs, so per-GPU weights
# are ~2x DEP8 (233 GB loaded; profiler floor ~0.879). At 0.93, run
# 29367944489 left only 2.9-4.8 GiB free while the sparse-attention
# indexer requested 4.2-6.1 GiB, causing CUDA OOMs during warmup. Use
# 0.90 to restore about 8.6 GiB/GPU of activation/workspace headroom
# while remaining above the profiler floor.
MEM_FRACTION_STATIC=0.90
CHUNKED_PREFILL_SIZE=32768
CUDA_GRAPH_ARGS=(--cuda-graph-max-bs-decode 128)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 The DP-attention branch launches sglang.launch_server with --cuda-graph-max-bs-decode (lines 153/163), a flag name that appears nowhere else in this repo — every other launcher, including the sibling MegaMoE DEP8 recipe sizing the identical 544 decode-graph batch (fixed_seq_len/dsv4_fp4_b300_sglang.sh:113), uses the plain --cuda-graph-max-bs. If SGLang's argparse rejects the -decode suffix, the server will fail to start for every dp-attn: true config (3 of the 5 search-space rows), which is exactly the MegaMoE DEP configuration this PR exists to rerun. Please confirm against the pinned SGLang image's server_args that this flag is real before merging; separately, the comment above it ("DEP8 ... serves conc up to 512") is now stale since this PR's own nvidia-master.yaml diff drops 512 from the DEP8 conc-list, leaving 196 as the new max.

Extended reasoning...

The flag. CUDA_GRAPH_ARGS=(--cuda-graph-max-bs-decode 544) (TP8, line 153) and (--cuda-graph-max-bs-decode 128) (TP4, line 163) are only reachable when DP_ATTENTION=true, which covers 3 of the 5 search-space rows in dsv4-fp4-b300-sglang-agentic-hicache (DEP4-none, DEP4-hicache, DEP8-none). A repo-wide search shows --cuda-graph-max-bs-decode exists nowhere else in InferenceX — not in any other SGLang launcher, and a git log -S pickaxe search shows this commit is the very first time the string has ever appeared in this repository's history. The strongest counter-evidence sits right next to it: benchmarks/single_node/fixed_seq_len/dsv4_fp4_b300_sglang.sh runs the same DeepSeek-V4 FP4 B300 MegaMoE DEP8 configuration (same --moe-a2a-backend megamoe, same SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK) and sizes the decode graph to the identical value, 544, but with the plain --cuda-graph-max-bs (line 113). This script's own non-DP fallback (line 191) also falls back to the plain flag. That is about as close to an apples-to-apples control as you get, and it points at a typo/transcription slip rather than an intentional, SGLang-supported decode-specific flag.\n\nWhy it matters. sglang.launch_server parses its CLI via argparse, which aborts the process with SystemExit(2) ("unrecognized arguments") on any unknown flag, before CUDA context creation or model load. If --cuda-graph-max-bs-decode isn't recognized by the pinned image (lmsysorg/sglang:nightly-dev-cu13-20260707-b4155233), every DP-attention job in this sweep — the exact B300 MegaMoE DEP recipe this PR is explicitly trying to preserve and rerun — fails immediately at startup. The PR's stated validation (bash -n, YAML parsing, load_config_files) only checks shell/YAML syntax; none of it constructs or exercises the actual sglang.launch_server argv, so this would slip through and only be caught once the GPU jobs actually run.\n\nAddressing the refutation. One verifier argued this is refuted by the PR's own evidence: the OOM analysis in the description says jobs from run 29367944489 reached CUDA warmup and died inside deep_gemm.fp8_paged_mqa_logits — which is downstream of argument parsing, so if the flag were invalid, those jobs would have died at parse time instead, before ever touching CUDA. That's a real observation, but it rests on an unverifiable assumption: that predecessor PR #2145's script used the exact same -decode spelling and that this PR's DEP4 lines are a byte-for-byte carryover. I could not find #2145 in this repository's git history (no remote is configured, and no prior commit ever contains "cuda-graph-max-bs-decode" per git log -S), and the PR description itself calls this a rebuild "on the latest main" of a PR whose diff had to be manually reconstructed (excluding B200 and changelog changes). A manual reconstruction is exactly the kind of step where a flag name could be mistyped even if the original #2145 script used the correct plain flag — we simply cannot confirm from what's in front of us that the run 29367944489 logs correspond to a config using the -decode spelling rather than the correct one. Given that ambiguity, and given that the one piece of concrete, in-repo, apples-to-apples evidence (the sibling fixed_seq_len recipe) uses the plain flag for the identical 544 value, I still think this needs the author to explicitly confirm the flag against the pinned SGLang image before merge rather than relying on an inference about an unrelated historical run.\n\nStep-by-step proof of the failure mode (if the flag is indeed invalid):\n1. A search-space entry with dp-attn: true, e.g. tp: 8, ep: 8, is scheduled — one of the 3 affected rows.\n2. The script enters the DP_ATTENTION=true branch (line ~119) and, since TP=8, sets CUDA_GRAPH_ARGS=(--cuda-graph-max-bs-decode 544) (line 153).\n3. SGLANG_CMD is assembled including "" (line ~229) and executed via "" >> "" 2>&1 &.\n4. sglang.launch_server's argparse.ArgumentParser.parse_args() encounters --cuda-graph-max-bs-decode, finds no matching add_argument, and calls parser.error(...), which prints "unrecognized arguments: --cuda-graph-max-bs-decode 544" and exits with status 2 — before any CUDA/model initialization.\n5. wait_for_server_ready polls the health port, never gets a response (the process already exited), and the job fails/hangs on the timeout instead of ever reaching the benchmark — for all 3 dp-attn rows, defeating the PR's stated purpose of rerunning exactly this B300 MegaMoE DEP configuration.\n\nFix. Confirm --cuda-graph-max-bs-decode is a recognized argument in the pinned SGLang nightly's server_args.py/launch_server before merge (e.g. via python -m sglang.launch_server --help against the actual image, or grepping the vendored SGLang source in the container). If it isn't, change both occurrences (lines 153, 163) to the plain --cuda-graph-max-bs, consistent with the sibling MegaMoE recipe and this script's own non-DP fallback. While touching this block, the comment directly above ("DEP8 (dp 8) serves conc up to 512") is also worth updating since this PR's own configs/nvidia-master.yaml diff removes 512 from the DEP8 conc-list, leaving 196 as the new max — a cosmetic follow-up, not a blocker on its own.

Comment on lines 14264 to +14269
agentic-coding:
- dram-utilization: 0.80
search-space:
- { tp: 4, kv-offloading: none, conc-list: [1, 4, 8, 16, 20, 24, 32] }
- { tp: 8, kv-offloading: none, conc-list: [1, 4, 8, 16, 32, 40, 48, 52, 56, 60, 64, 72] }
- { tp: 4, ep: 4, dp-attn: true, kv-offloading: none, conc-list: [8, 16, 24, 32, 40, 64], router: { name: sglang-router, version: "0.3.2" } }
- { tp: 4, ep: 4, dp-attn: true, kv-offloading: dram, kv-offload-backend: { name: hicache }, conc-list: [32, 40, 48, 56, 64, 72, 80, 88, 96, 128], router: { name: sglang-router, version: "0.3.2" } }
- { tp: 8, ep: 8, dp-attn: true, kv-offloading: none, conc-list: [52, 72, 100, 128, 144, 196, 512], router: { name: sglang-router, version: "0.3.2" } }
- { tp: 4, kv-offloading: none, conc-list: [1, 2, 4, 8, 16] }
- { tp: 8, kv-offloading: none, conc-list: [1, 2, 4, 8, 16, 32, 40] }
- { tp: 4, ep: 4, dp-attn: true, kv-offloading: none, conc-list: [8, 16, 24, 32, 40], router: { name: sglang-router, version: "0.3.2" } }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 This PR changes the B300 benchmark recipe (mem-fraction-static, MegaMoE DEP path, new low-latency TP path, several SGLANG_* env vars) and the corresponding search-space in configs/nvidia-master.yaml, but appends no entry to perf-changelog.yaml. Since run-sweep.yml is path-filtered on perf-changelog.yaml and process_changelog.py derives the entire sweep matrix from newly-appended changelog lines, merging as-is means the B300 rerun this PR exists to produce will never execute. Please append a perf-changelog.yaml entry keyed to dsv4-fp4-b300-sglang-agentic-hicache (config-key, description, PR link) at the end of the file.

Extended reasoning...

What the bug is: The PR's stated purpose is to "rerun only the B300 configuration" for dsv4-fp4-b300-sglang-agentic-hicache with a lowered mem-fraction-static (0.93 → 0.90) to fix an observed CUDA OOM, plus a broader recipe overhaul (MegaMoE DEP path, a new low-latency TP-only path, several new SGLANG_* env vars, and revised conc-list search-space entries). The changed-files set for this PR is exactly two files — benchmarks/single_node/agentic/dsv4_fp4_b300_sglang.sh and configs/nvidia-master.yaml. No entry is appended to perf-changelog.yaml.

The code path that triggers it: .github/workflows/run-sweep.yml gates both its push (lines 25-26) and pull_request (lines 35-36) triggers with paths: ["perf-changelog.yaml"]. Since this PR never touches that file, the entire sweep workflow (including check-changelog, the reuse-sweep gate, and the actual benchmark jobs) will not fire on this PR, and will not fire on the post-merge push to main either. Even setting aside the workflow-level path filter, the sweep's matrix is itself derived from perf-changelog.yaml: utils/process_changelog.py's get_added_lines() git-diffs only that file between base and head, and main() explicitly raises ValueError("No additions found in the changelog file.") when there are no appended lines (utils/process_changelog.py:128-129). The config-keys from each appended changelog entry are what get resolved against the master config via get_config_keys_from_master() to build the actual sweep — so an empty changelog diff means zero configs get selected, config-key resolution never runs, and the dsv4-fp4-b300-sglang-agentic-hicache search-space this PR just edited is never benchmarked.

Why existing code doesn't prevent it: There is no other trigger path. Labels like full-sweep-fail-fast only affect fail-fast behavior of matrix jobs that are already running — they don't bypass the perf-changelog.yaml path filter. validate_perf_changelog.py (or equivalent validation) does not error out when the changelog is left unchanged, so nothing blocks the merge; the sweep just silently never runs. Recent config-changing PRs in this repo (e.g. #2158/#2222, #2197, #2198) consistently append a changelog entry alongside their config edits, and the immediate predecessor to this PR (#2145) also lacks one, showing this omission isn't a one-off outlier but a real gap that AGENTS.md and the PR checklist both explicitly call out as required ("append a perf-changelog.yaml entry (required — triggers benchmarks)").

Impact: Concretely, merging this PR as-is makes it a functional no-op for its own stated purpose. The mem-fraction-static OOM fix, the MegaMoE DEP path, the new low-latency TP-only path, and the revised concurrency search-space all land on main, but none of them get exercised by CI — the exact scenario (DEP4 CUDA OOM in deep_gemm.fp8_paged_mqa_logits) that motivated this PR will not be re-validated. A maintainer or the author would need a follow-up PR just to actually trigger the benchmark.

Step-by-step proof:

  1. git diff main...HEAD -- perf-changelog.yaml for this PR is empty (only dsv4_fp4_b300_sglang.sh and nvidia-master.yaml are in <changed-files>).
  2. On pull_request, GitHub Actions evaluates run-sweep.yml's trigger: the event's changed-file set intersected with paths: ["perf-changelog.yaml"] is empty, so the workflow does not run at all, regardless of labels applied.
  3. Suppose the workflow were manually forced to run anyway (e.g., via workflow_dispatch): the setup job calls process_changelog.py --base-ref ... --head-ref ..., which calls get_added_lines() — a git diff scoped to perf-changelog.yaml only. Since no lines were added there, added_yaml.strip() is empty and main() raises ValueError("No additions found in the changelog file."), hard-failing before any config-key resolution or sweep construction happens.
  4. Either way, the dsv4-fp4-b300-sglang-agentic-hicache config — the one this PR just modified — never gets included in a benchmark run.

How to fix: Append a perf-changelog.yaml entry at the end of the file with config-key: dsv4-fp4-b300-sglang-agentic-hicache, a short description of the mem-fraction/MegaMoE/low-latency changes, and a link to this PR — mirroring the format used by the sibling PRs (#2158/#2222, #2197, #2198) that touched nvidia-master.yaml.

@github-actions

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentx AgentX benchmarks, recipes, and infrastructure

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant